跳到主要内容

K3s 配置 letsencrypt 域名 DNS-01

DNS-01 的校验原理

利用 DNS 提供商的 API Key 拿到用户 DNS 控制权限。此方法不需要使用 Ingress,并且支持泛域名证书。在 Let’s Encrypt 为 ACME 客户端提供令牌后,ACME 客户端 cert-manager 将创建从该令牌和账户密钥派生的 TXT 记录,并将该记录放在 _acme-challenge.<YOUR_DOMAIN>。Let’s Encrypt 将向 DNS 系统查询该记录,找到匹配项即可颁发证书。

配置测试服务

先编写一个测试服务,用于测试证书是否生效

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-test-deployment
namespace: qjwwy-dev
spec:
replicas: 1
selector:
matchLabels:
app: nginx-test
template:
metadata:
labels:
app: nginx-test
namespace: qjwwy-dev
spec:
containers:
- name: nginx-test
image: nginx:latest
ports:
- containerPort: 80

---

apiVersion: v1
kind: Service
metadata:
name: nginx-test-service
namespace: qjwwy-dev
spec:
selector:
app: nginx-test
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP

配置 ClusterIssuer

因为 dns 托管在阿里云,且 cert-manager 不支持 alidns,只能通过 webhook 方式部署,来扩展 DNS 提供商。

配置 alidns-webhook

这里以阿里 dns + alidns-webhook 方式为例。

wget kubectl apply -f https://raw.githubusercontent.com/pragkent/alidns-webhook/master/deploy/bundle.yaml

修改文件中的 acme.yourcompany.com

sed -i s/'acme.yourcompany.com'/'acme.qjwwy.com'/g bundle.yaml

创建一个包含阿里 dns 凭据的 secert,这里使用 base64 编码,可以使用以下命令生成:

echo -n YOUR_ACCESS_KEY | base64
apiVersion: v1
kind: Secret
metadata:
name: alidns-secret
namespace: cert-manager
data:
access-key: YOUR_ACCESS_KEY # base64
secret-key: YOUR_SECRET_KEY # base64

或者使用如下命令行方式创建

kubectl -n cert-manager create secret generic alidns-secret --from-literal=access-key='YOUR_ACCESS_KEY' --from-literal=secret-key='YOUR_SECRET_KEY'

请注意,如果使用的是阿里云的子账户,还需要配置 alidns 的 RAM

{
"Version": "1",
"Statement": [
{
"Action": "*",
"Resource": "acs:alidns:*:*:domain/<域名>",
"Effect": "Allow"
},
{
"Action": [
"alidns:DescribeSiteMonitorIspInfos",
"alidns:DescribeSiteMonitorIspCityInfos",
"alidns:DescribeSupportLines",
"alidns:DescribeDomains",
"alidns:DescribeDomainNs",
"alidns:DescribeDomainGroups"
],
"Resource": "acs:alidns:*:*:*",
"Effect": "Allow"
}
]
}

创建 ClusterIssuer

在 cert-manager 中,ClusterIssuer 用于配置证书的签发,包括 Let's Encrypt。创建一个 ClusterIssuer 的 YAML 文件,例如 letsencrypt-cluster-issuer.yaml

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-staging
spec:
acme:
# Change to your letsencrypt email
email: alsritter@outlook.com
server: https://acme-v02.api.letsencrypt.org/directory
privateKeySecretRef:
name: letsencrypt-staging-account-key
solvers:
- dns01:
webhook:
groupName: acme.qjwwy.com # 须和 bundle.yaml 文件中定义的groupname 一致
solverName: alidns
config:
region: ""
accessKeySecretRef:
name: alidns-secret
key: access-key
secretKeySecretRef:
name: alidns-secret
key: secret-key

这里使用的是阿里云的 DNS

  • your-email@example.com:你的电子邮件地址。
  • YOUR_ACCESS_KEY_ID:阿里云账户的 API 密钥 ID。

测试服务

再创建一个 Ingress 文件,例如 example-ingress-wildcard.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example-ingress-wildcard
namespace: qjwwy-dev
annotations:
cert-manager.io/cluster-issuer: letsencrypt-staging
spec:
tls:
- hosts:
- "*.example.com"
secretName: example-tls-secret-wildcard
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-test-service
port:
number: 80

现在可以检查是否创建了 certificate

# 需要等一会才会变成 True
kubectl get certificate -n qjwwy-dev -w

查看证书详情

kubectl describe certificate -n qjwwy-dev

# 找到证书
kubectl get secrets -n qjwwy-dev

kubectl get secrets example-tls-secret-wildcard -n qjwwy-dev -o json |jq --raw-output '.data["tls.crt"]'|base64 -d #从secert中解析证书

然后验证一下证书

https://www.chinassl.net/ssltools/decoder-ssl.html

发现可以正常解析,证书已经生效了。

再访问测试一下

https://test.quicktoolset.top/